﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using ZhongJia.Lock.Infrastructure.Web;
using ZhongJia.Lock.Core.Services;
using ZhongJia.Lock.Core.Dto;
using ZhongJia.Lock.Infrastructure.Data;
using ZhongJia.Lock.Core.Domain;
using Microsoft.EntityFrameworkCore;
using ZhongJia.Lock.Web.Constants;
using System.Linq.Expressions;

// For more information on enabling MVC for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860

namespace ZhangJia.Lock.Web.Controllers
{
    [Route("api/[Controller]")]
    [Authorize()]
    public class LockController : BaseController
    {
        private readonly ITcpService _tcpService;
        private readonly IRepository<OpenLockHistory> _openLockHistoryRepository;
        private readonly IRepository<LockDevice> _lockDeviceRepository;
        private readonly IRepository<Community> _communityRepository;

        public LockController(
            ITcpService tcpService,
            IRepository<OpenLockHistory> openLockHistoryRepository,
            IRepository<LockDevice> lockDeviceRepository,
            IRepository<Community> communityRepository)
        {
            _tcpService = tcpService;
            _openLockHistoryRepository = openLockHistoryRepository;
            _lockDeviceRepository = lockDeviceRepository;
            _communityRepository = communityRepository;
        }

        /// <summary>
        /// 返回锁列表设备是否在线
        /// </summary>
        /// <remarks>
        /// 请求参数说明和请求返回说明
        ///  
        ///     GET /api/lock
        ///     {
        ///        "deviceIds": ["guid"],  --设备id数组
        ///     }
        ///     response 
        ///     [{
        ///         "deviceId":guid  --设备id
        ///         "IsOnline":true  --是否在线
        ///     }]
        /// </remarks>
        /// <returns></returns>
        /// <returns></returns>
        [HttpGet]
        public async Task<IActionResult> GetList(Guid[] deviceIds)
        {
            if (deviceIds.Length == 0)
                return Sucessed();

            var devices = await _lockDeviceRepository.Query().Where(l => !l.IsForICCard && !l.IsDelete).ToListAsync();
            return Sucessed(deviceIds.Select(d =>
            new
            {
                DeviceId = d,
                IsOnline = _tcpService.OnLineDevices.Any(t => t.Value == devices.FirstOrDefault(ld => ld.Id == d)?.SerialNumber)
            }));
        }

        /// <summary>
        /// 创建锁设备
        /// </summary>
        /// <remarks>
        /// params description.
        ///  
        ///     POST /api/lock
        ///     {
        ///        "name": "东门",  --锁设备名称
        ///        "CommunityId": "guid", --小区Id
        ///        "IsGate": false   --是否是小区id,
        ///        "UnitName":"一栋2单元"  -- 如果不是大门，传单元名称，单元名称唯一包含楼栋
        ///     }
        ///     response 
        ///     {
        ///         "deviceId":guid  --返回设备id
        ///     }
        /// </remarks>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost()]
        public async Task<IActionResult> Create([FromBody] CreateLockInput input)
        {
            var community = await _communityRepository.Query().FirstOrDefaultAsync(c => c.Id == input.CommunityId && !c.IsDeleted);
            if (community == null)
                return Error(Errors.community_not_found.ToString(), "小区id非法");

            var serialNumber = $"{community.Number}-";
            var lockNumber = 0;
            if (!input.IsGate)
            {
                var unitNumber = await _lockDeviceRepository.Query().CountAsync(l => l.CommunityId == community.Id && !l.IsGate && !l.IsForICCard );
                lockNumber = await _lockDeviceRepository.Query().CountAsync(l => l.CommunityId == community.Id && !l.IsGate && l.UnitName == input.UnitName && !l.IsForICCard) + 1;
                serialNumber += $"{unitNumber}-{lockNumber}";
            }
            else
            {
                lockNumber = await _lockDeviceRepository.Query().CountAsync(l => l.CommunityId == community.Id && l.IsGate && !l.IsForICCard) + 1;
                serialNumber += $"0-{lockNumber}";
            }
            var device = new LockDevice
            {
                CommunityId = community.Id,
                SerialNumber = serialNumber,
                IsGate = input.IsGate,
                UnitName = input.UnitName,
            };
            _lockDeviceRepository.Add(device);
            await _lockDeviceRepository.SaveChangeAsync();
            return Sucessed(new { DeviceId = device.Id });
        }

        /// <summary>
        /// 开锁
        /// </summary>
        /// <remarks>
        /// params description.
        ///  
        ///     POST /api/lock/open
        ///     {
        ///        "name": "张三",  --开锁人姓名
        ///        "deviceId": "guid"   --设备id
        ///     }
        ///     response 
        ///     {
        ///         "IsSuccessed":true  --返回开锁是否成功
        ///         "Error": LockNotOnlline --锁离线
        ///                  SendFailed --信号发送不成功
        ///     }
        /// </remarks>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("open")]
        public async Task<IActionResult> Open([FromBody] OpenLockInput input)
        {
            var lockDevice = await _lockDeviceRepository.Query().FirstOrDefaultAsync(l => l.Id == input.DeviceId && l.IsGate && !l.IsForICCard && !l.IsDelete);
            if (lockDevice == null)
                return Error(Errors.lockDevice_not_found.ToString(), "设备id非法");

            var result = _tcpService.Open(lockDevice.SerialNumber);
            return Sucessed(result);
        }

        /// <summary>
        /// 删除锁
        /// </summary>
        /// <remarks>
        /// params description.
        ///  
        ///     HttpDelete /api/lock/{deviceId:guid}
        ///     {
        ///        "deviceId": "guid"   --设备id
        ///     }
        ///     response (statusCode == 200 说明操作成功)
        ///     {
        ///     }
        /// </remarks>
        /// <returns></returns>
        [HttpDelete("{deviceId:guid}")]
        public async Task<IActionResult> Delete(Guid deviceId)
        {
            var lockDevice = await _lockDeviceRepository.Query().FirstOrDefaultAsync(l => l.Id == deviceId && l.IsGate && !l.IsForICCard && !l.IsDelete);
            if (lockDevice == null)
                return Error(Errors.lockDevice_not_found.ToString(), "设备id非法");

            lockDevice.IsDelete = true;
            await _lockDeviceRepository.SaveChangeAsync();
            return Sucessed();
        }
    }
}
